/* 
 * Shuriken is the legal property of its developers. Please refer to the
 * COPYRIGHT file distributed with this
 * source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices; 

namespace Shuriken.Core.Utils
{

    /// <summary>
    /// Limits the application to single instance
    /// </summary>
    /// <remarks>
    /// How to limit 32-bit applications to one instance in Visual C++
    /// http://support.microsoft.com/kb/243953/en-us
    /// </remarks>
    public class LimitSingleInstance
    {
        private int m_LastWin32Error;
        private System.IntPtr m_hMutex; 


        public const int ERROR_ALREADY_EXISTS = 183;

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool ReleaseMutex(IntPtr hMutex);

        [DllImport("kernel32.dll")]
        static extern void SetLastError(uint dwErrCode);

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="MutexName">mutex name</param>
        public LimitSingleInstance(string MutexName)
        {
            SetLastError(0);
            m_hMutex = CreateMutex(IntPtr.Zero, true, MutexName); 
            m_LastWin32Error = Marshal.GetLastWin32Error();
        }

        /// <summary>
        /// Destructor
        /// </summary>
        /// <remarks>
        /// Releasing mutex if we acquired it. 
        /// </remarks>
        ~LimitSingleInstance()
        {
            bool release; 
            if (m_hMutex != IntPtr.Zero)
            {
                SetLastError(0);
                release = ReleaseMutex(m_hMutex);
                m_hMutex = System.IntPtr.Zero;
                m_LastWin32Error = Marshal.GetLastWin32Error();
            }
        }

        /// <summary>
        /// Another Instance Running 
        /// </summary>
        /// <returns>true, if another instance of the application is running</returns>
        public bool IsAnotherInstanceRunning()
        {
            return (ERROR_ALREADY_EXISTS == m_LastWin32Error); 
        }
    }
}
